package com.study.httpserver.htserver;

import com.study.httpserver.request.HttpRequest;
import com.study.httpserver.response.HttpResponse;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.URI;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by meen on 2017/12/7.
 */
public class Dispatcher implements HttpHandler {

    private static final String POST = "POST";
    private static final String GET = "GET";
    private static final String charset_utf8 = "utf-8";

    private HandlerMapping handlerMapping;

    public Dispatcher(HandlerMapping handlerMapping) {
        this.handlerMapping = handlerMapping;
    }

    private static Logger logger = LoggerFactory.getLogger(Dispatcher.class);

    public void handle(HttpExchange exchange) throws IOException {
        String method = exchange.getRequestMethod();
        URI uri = exchange.getRequestURI();
        String uriString = uri.toString();
        logger.info("receive request method:{} uri:{}", method, uriString);
        Map<String, List<String>> headers = exchange.getRequestHeaders();
        Map<String, String[]> params = null;
        if (method.equalsIgnoreCase(GET)) {
            int index = uriString.indexOf('?');
            if (index == -1) {
                throw new RuntimeException("uri错误" + uriString);
            }
            String queryString = uriString.substring(index + 1, uriString.length());
            params = resolve(queryString);
        } else if (method.equalsIgnoreCase(POST)) {
            InputStream inputStream = exchange.getRequestBody();


            BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, charset_utf8));//防止乱码
            String queryString = "";
            String line;
            while ((line = in.readLine()) != null) {
                queryString += line;
            }
            logger.info("receive request params:{}", queryString);
            params = resolve(queryString);
        }
        HttpRequest httpRequest = new HttpRequest(method, uriString, headers, params);
        String path = uri.getPath().replace("/","");
        logger.info("receive request path:{}", path);
        LogicHandler handler = handlerMapping.getHandler(path);
        if (handler == null) {
            logger.error("can not find handler : {}", path);
            return;
        }
        HttpResponse httpResponse = new HttpResponse();
        httpResponse.setOutputStream(exchange.getResponseBody());
//        Headers responseHeaders = exchange.getResponseHeaders();
//        responseHeaders.set("Content-Type", "text/plain");
        handler.doAction(httpRequest, httpResponse);
    }

    private Map<String, String[]> resolve(String queryString) {
        Map<String, String[]> paramsMap = new HashMap<String, String[]>();
        if (queryString != null && queryString.length() > 0) {
            int ampersandIndex, lastAmpersandIndex = 0;
            String subStr, param, value;
            String[] paramPair, values, newValues;
            do {
                ampersandIndex = queryString.indexOf('&', lastAmpersandIndex) + 1;
                if (ampersandIndex > 0) {
                    subStr = queryString.substring(lastAmpersandIndex, ampersandIndex - 1);
                    lastAmpersandIndex = ampersandIndex;
                } else {
                    subStr = queryString.substring(lastAmpersandIndex);
                }
                paramPair = subStr.split("=");
                param = paramPair[0];
                value = paramPair.length == 1 ? "" : paramPair[1];
                try {
                    value = URLDecoder.decode(value, charset_utf8);
                } catch (UnsupportedEncodingException ignored) {

                }
                if (paramsMap.containsKey(param)) {
                    values = paramsMap.get(param);
                    int len = values.length;
                    newValues = new String[len + 1];
                    System.arraycopy(values, 0, newValues, 0, len);
                    newValues[len] = value;
                } else {
                    newValues = new String[]{value};
                }
                paramsMap.put(param, newValues);
            } while (ampersandIndex > 0);
        }
        return paramsMap;
    }


}
